import os
import json
import requests
from flask import Flask, render_template, request, session, redirect, url_for

import random

def next_nonce():
    return random.randint(0, 9223372036854775807 - 1)

app = Flask(__name__)
app.config.from_pyfile('config.py')

# util func
def current_user():
    user = session.get('name')
    if user:
        return user
    else:
        return 'test'


def current_chain_path():
    chain_path = session.get('chain-path')
    if chain_path:
        return chain_path
    else:
        return 'payment.cita'


# such as payment.cita.0xa14d43c1d1f9c957359569dedc9a2cefac2b3553
def contract_path():
    chain_path = current_chain_path()
    contract_addr = app.config.get('SUPPLY_CONTRACT_ADDR_MAP')[chain_path]
    return '.'.join([chain_path, contract_addr])


# such as http://172.16.186.234:8250/resource/sendTransaction
def send_tx_url():
    router_url = app.config.get('ROUTER_URL')
    return router_url + '/resource/sendTransaction'


# such as http://172.16.186.231:8250/resource/call
def call_url():
    router_url = app.config.get('ROUTER_URL')
    return router_url + '/resource/call'


@app.route('/')
def index():
    return redirect(url_for('login'))


@app.route('/login', methods=['GET', 'POST'])
def login():
    errors = []
    if request.method == "POST":
        user = request.form['user']
        pwd = request.form['pwd']
        chain_path = request.form['chain-path']
        if user == pwd:
            print('login:', user)
            session['name'] = user
            session['chain-path'] = chain_path
            return redirect(url_for('bar'))
        else:
            errors.append(
                "Unable to login. Please make sure it's valid and try again."
            )
    return render_template('login.html', errors=errors)


@app.route('/bar', methods=['GET', 'POST'])
def bar():
    return render_template('bar.html')


@app.route('/new', methods=['GET', 'POST'])
def new():
    errors = []
    if request.method == "POST":
        # get url that the user has entered
        try:
            cargo_id = request.form['cargo_id']
            cargo_uri = request.form['cargo_uri']
            print('new cargo:', cargo_id, cargo_uri)
            print('current user:', current_user())

            # post router
            # {"version":"1","data":{"path":"payment.cita.0xa14d43c1d1f9c957359569dedc9a2cefac2b3553","method": "newCargo","args":[cargoId, uri],"nonce":123456,"luyuSign":user}}
            data = {"path": contract_path(), "method": "newCargo", "args": [cargo_id, cargo_uri], "nonce": next_nonce(), "luyuSign": "", "sender": current_user()}
            post_param = {"version": "1","data": data}
            headers = {"Content-Type": "application/json"}
            response = requests.post(send_tx_url(), data=json.dumps(post_param), headers=headers)
            errors.append(response.text)
        except:
            errors.append(
                "Unable to new cargo. Please make sure it's valid and try again."
            )

    return render_template('new.html', errors=errors)


@app.route('/show', methods=['GET', 'POST'])
def show():
    errors = []
    cargo_info = None
    export_info = None
    if request.method == "POST":
        # get url that the user has entered
        try:
            cargo_id = request.form['cargo_id']
            print('show cargo:', cargo_id)
            print('current user:', current_user())

            # call ownerOf/cargoURI and getExportRequestByCargoId
            data = {"path": contract_path(), "method": "ownerOf", "args": [cargo_id], "nonce": next_nonce(), "luyuSign": "", "sender": current_user()}
            post_param = {"version": "1","data": data}
            headers = {"Content-Type": "application/json"}
            response = requests.post(call_url(), data=json.dumps(post_param), headers=headers)
            owner = json.loads(response.text)['data']['result'][0]
            if owner == '0x0000000000000000000000000000000000000000':
                raise ValueError

            data = {"path": contract_path(), "method": "cargoURI", "args": [cargo_id], "nonce": next_nonce(), "luyuSign": "", "sender": current_user()}
            post_param = {"version": "1","data": data}
            headers = {"Content-Type": "application/json"}
            response = requests.post(call_url(), data=json.dumps(post_param), headers=headers)
            uri = json.loads(response.text)['data']['result'][0]

            cargo_info = (owner, uri)

            data = {"path": contract_path(), "method": "getExportRequestByCargoId", "args": [cargo_id], "nonce": next_nonce(), "luyuSign": "", "sender": current_user()}
            post_param = {"version": "1","data": data}
            headers = {"Content-Type": "application/json"}
            response = requests.post(call_url(), data=json.dumps(post_param), headers=headers)
            ret = json.loads(response.text)
            if ret['data']['result'] == None:
                to_chain_path = ""
                receiver = ""
            else:
                result = ret['data']['result']
                to_chain_path = result[0]
                receiver = result[1]
            export_info = (to_chain_path, receiver)
        except:
            errors.append(
                "Unable to find cargo. Please make sure it's valid and try again."
            )

    return render_template('show.html', errors=errors, cargo_info=cargo_info, export_info=export_info)


@app.route('/transfer', methods=['GET', 'POST'])
def transfer():
    errors = []
    if request.method == "POST":
        # get url that the user has entered
        try:
            cargo_id = request.form['cargo_id']
            to = request.form['to']
            print('transfer cargo:', cargo_id, to)
            print('current user:', current_user())
            
            data = {"path": contract_path(), "method": "transfer", "args": [to, cargo_id], "nonce": next_nonce(), "luyuSign": "", "sender": current_user()}
            post_param = {"version": "1","data": data}
            headers = {"Content-Type": "application/json"}
            response = requests.post(send_tx_url(), data=json.dumps(post_param), headers=headers)
            errors.append(response.text)
        except:
            errors.append(
                "Unable to transfer cargo. Please make sure it's valid and try again."
            )

    return render_template('transfer.html', errors=errors)


@app.route('/export', methods=['GET', 'POST'])
def export():
    errors = []
    if request.method == "POST":
        # get url that the user has entered
        try:
            cargo_id = request.form['cargo_id']
            to_chain_path = request.form['to_chain_path']
            receiver = request.form['receiver']
            print('export cargo:', cargo_id, to_chain_path, receiver)
            print('current user:', current_user())
            
            data = {"path": contract_path(), "method": "exportRequest", "args": [cargo_id, to_chain_path, receiver], "nonce": next_nonce(), "luyuSign": "", "sender": current_user()}
            post_param = {"version": "1","data": data}
            headers = {"Content-Type": "application/json"}
            response = requests.post(send_tx_url(), data=json.dumps(post_param), headers=headers)
            errors.append(response.text)
        except:
            errors.append(
                "Unable to export cargo. Please make sure it's valid and try again."
            )

    return render_template('export.html', errors=errors)


if __name__ == '__main__':
    app.run()
